package com.lry.crawlers.fiction.processor;

import com.alibaba.fastjson.JSONObject;
import com.jnewbie.JProcessor;
import com.jnewbie.request.JPage;
import com.lry.crawlers.fiction.entity.FictionChapter;
import com.lry.crawlers.fiction.entity.FictionVariable;
import com.lry.crawlers.fiction.pipeline.FictionPipeline;
import com.lry.crawlers.fiction.service.FictionChapterService;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FictionPlusUpJProcessor extends JProcessor {
    public volatile static int allUrl = 0;
    public Map<String,Object> map;
    private FictionPipeline fictionPipeline;
    private FictionChapterService fictionChapterService;
    private FictionVariable fictionVariable;
    public String infId;

    public FictionPlusUpJProcessor() {
    }


    public FictionPlusUpJProcessor(String infId,Map<String,Object> map, FictionPipeline fictionPipeline,FictionChapterService fictionChapterService,FictionVariable fictionVariable) {
        this.infId = infId;
        this.map = map;
        this. fictionPipeline = fictionPipeline;
        this.fictionChapterService = fictionChapterService;
        this.fictionVariable = fictionVariable;
    }



    @Override
    public JPage process(JPage jPage) {
        
        if(jPage.getUrl().contains("www.baidu.com")){
            jPage.addGoUrls(new ArrayList<>(map.keySet()));
            return jPage;
        }
        LinkedHashMap<String, Object> map = new LinkedHashMap<>();
        LinkedHashMap<String, String> hmapz = JSONObject.parseObject(JSONObject.toJSONString(fictionVariable), LinkedHashMap.class);
        Field[] declaredFields = fictionVariable.getClass().getDeclaredFields();
        LinkedHashMap<String, String> hmap = new LinkedHashMap<>();
        for (Field declaredField : declaredFields) {
            hmap.put(declaredField.getName(), hmapz.get(declaredField.getName()));
        }
        hmap.remove("mode");
        int chapterSort = Integer.parseInt(String.valueOf(hmap.remove("chapterSort")));
        hmap.remove("id");
        hmap.remove("deleted");
        hmap.remove("creationTime");
        hmap.remove("searchUrl");
        hmap.remove("name");
        hmap.remove("encoding");
        hmap.remove("url");
        hmap.remove("protocol");
        for (String s : hmap.keySet()) {
            try{
                String key = hmap.get(s);
                if (key != null && key.contains("${url}"))
                    key =  key.replace("${url}", jPage.getUrl());
                //判断是否包含固定值
                if (key != null && key.length() > 0) {
                    if (!key.contains("-@") && !key.contains("@-")) {
                        //xpath与正则提取出来
                        String[] x_z = key.split("-!-");
                        //获取xpath与正则匹配的值
                        List<String> result = null;
                        try {
                            result = !x_z[0].equals("") ? jPage.xpath(x_z[0]).regex(x_z.length != 1 ? x_z[1] : "(.*)").trim().getAll() :
                                    x_z.length > 1 && !x_z[1].equals("") ? jPage.regex(x_z[1]).trim().getAll() : null;
                        } catch (Exception e) {

                        }
                        //如果获取的值不为空，那就存放
                        if (result != null && result.size() != 0) {
                            map.put(s, result);
                        }
                    } else {
                        //把非固定的值提取出来
                        Pattern pattern = Pattern.compile("-@(.*?)@-", Pattern.DOTALL | Pattern.MULTILINE);
                        Matcher matcher = pattern.matcher(key);
                        List<String> result = null;
                        while (matcher.find()) {
                            //xpath与正则提取出来
                            String[] x_z = matcher.group(1).split("-!-");
                            //获取xpath与正则匹配的值
                            List<String> res = null;
                            try {
                                res = !x_z[0].equals("") ? jPage.xpath(x_z[0]).regex(x_z.length != 1 ? x_z[1] : "(.*)").trim().getAll() :
                                        x_z.length > 1 && !x_z[1].equals("") ? jPage.regex(x_z[1]).trim().getAll() : null;
                            } catch (Exception e) {
                                e
                                        .printStackTrace();
                            }

                            //判断值是否存在
                            if (res != null && res.size() != 0) {
                                //第一次就新增
                                if (result == null) {
                                    result = new ArrayList<>();
                                    for (String re : res) {
                                        result.add(key.replaceFirst("-@(.*?)@-", re));
                                    }
                                    //不是第一次就修改
                                } else {
                                    int j = 0;
                                    String bak = null;
                                    for (String re : res) {
                                        try {
                                            bak = result.get(j);
                                            result.set(j, result.get(j).replaceFirst("-@(.*?)@-", re));
                                        }catch (IndexOutOfBoundsException e){
                                            result.add(j, bak.replaceFirst("-@(.*?)@-", re));
                                        }
                                        j++;
                                    }
                                }
                            }
                        }
                        //判断是否为空，不为空，就存入值，并去除未匹配的-@.*?@-
                        if (result != null && result.size() != 0) {
                            if(result.toString().contains("-@") &&result.toString().contains("@-")) {
                                for (int i = 0; i < result.size(); i++) {
                                    String bak = result.get(i);
                                    if (bak.contains("-@") && bak.contains("@-"))
                                        result.set(i, bak.replaceFirst("-@(.*?)@-", ""));
                                }
                            }
                            map.put(s, result);
                        }
                    }
                }
                //判断是值否为空，不为空，就开始处理
                if (map.get(s) != null) {
                    List<String> tag = (List<String>) map.get(s);
                    switch (s) {
                        case "goUrl":
                            jPage.addGoUrls(tag);
                            break;
                        case "chapterPage":
                            jPage.addGoUrls(tag);
                            break;
                        case "title":
                            Object o = jPage.delTag(UUID.nameUUIDFromBytes((jPage.getUrl()+ "details").getBytes()).toString());
                            HashMap<String, Object> omap = new HashMap<>();
                            if(o==null) {
                                String updateUrl = jPage.getUrl();
                                omap.put("title", ((List<String>) map.get("title")).get(0));
                                try{
                                    omap.put("descs", ((List<String>) map.get("descs")).get(0));
                                }catch (Exception e){omap.put("descs","");}
                                try {
                                    omap.put("author", ((List<String>) map.get("author")).get(0));
                                }catch (Exception e){omap.put("author","");}
                                try {
                                    String rex = "^[1-9]\\d*(\\.\\d+)?$";
                                    Pattern p = Pattern.compile(rex);
                                    Matcher m = p.matcher(((List<String>) map.get("updateTime")).get(0));
                                    if(m.find()){
                                        Date date = new Date(Long.parseLong(((List<String>) map.get("updateTime")).get(0))*1000);
                                        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
                                        String dateString = formatter.format(date);
                                        omap.put("updateTime", dateString);
                                    }else{
                                        omap.put("updateTime", ((List<String>) map.get("updateTime")).get(0));
                                    }                                }catch (Exception e){omap.put("updateTime",new Date());}
                                try {
                                    omap.put("fictionType", ((List<String>) map.get("fictionType")).get(0));
                                }catch (Exception e){omap.put("fictionType","");}
                                try {
                                    omap.put("cover", ((List<String>) map.get("cover")).get(0));
                                }catch (Exception e){omap.put("cover","");}
                                omap.put("updateUrl", updateUrl);
                            }else {
                                omap =( HashMap<String, Object>) o;
                            }
                            if(map.get("goUrl")!=null){
                                String goUrl = ((List<String>) map.get("goUrl")).get(0);
                                jPage.addTag(UUID.nameUUIDFromBytes((goUrl+"details").getBytes()).toString(),omap);
                            }else if (map.get("chapterPage")!=null){
                                String chapterPage = ((List<String>) map.get("chapterPage")).get(0);
                                jPage.addTag(UUID.nameUUIDFromBytes((chapterPage+"details").getBytes()).toString(),omap);
                            }else{
                                jPage.addTag(UUID.nameUUIDFromBytes((jPage.getUrl()+"details").getBytes()).toString(),omap);
                            }
                            break;

                        case "chapterUrl":
                            //判断是否还要下一页，还要就把数据放到，以下一页URL为key的map中
                            String fictionId = (String) jPage.delTag(UUID.nameUUIDFromBytes(jPage.getUrl().getBytes()).toString());
                            List<String> chapterUrls = (List<String>) jPage.delTag(UUID.nameUUIDFromBytes((jPage.getUrl()+"chapterUrls").getBytes()).toString());
                            List<String> chapterTitles =  (List<String>) jPage.delTag(UUID.nameUUIDFromBytes((jPage.getUrl()+"chapterTitles").getBytes()).toString());
                            Map<String, Object> details =  (Map<String, Object>) jPage.delTag(UUID.nameUUIDFromBytes((jPage.getUrl()+"details").getBytes()).toString());

                            boolean one  = (fictionId == null);
                            if (one) {
                                fictionId = (String)this.map.get(jPage.getUrl());
                                chapterUrls = tag;
                                chapterTitles = (List<String>)map.get("chapterTitle");
                            }
                            if(map.get("chapterPage") ==null) {
                                if (!one) {
                                    chapterUrls.addAll(tag);
                                    chapterTitles.addAll((List<String>)map.get("chapterTitle"));
                                }
                                jPage.addTag(UUID.nameUUIDFromBytes(jPage.getUrl().getBytes()).toString(), fictionId);
                                //获取现在的章节数量
                                int xsize = chapterUrls.size();
                                //生成需更新的章节对应排序
                                List<Integer> sortt = new ArrayList();
                                for(int i=0;i<chapterTitles.size();i++){
                                    sortt.add(i);
                                }

                                List<FictionChapter> fictionChapters = fictionChapterService.selectByFictionId(fictionId);
                                List<Integer> duplicates= fictionChapterService.removeDuplicates(chapterTitles,fictionChapters);
                                ArrayList<String> chapterId = new ArrayList<>();
                                for (String chapteru : chapterUrls) {
                                    chapterId.add(UUID.nameUUIDFromBytes(chapteru.getBytes()).toString());
                                }
                                if(chapterSort ==1){
                                    Collections.reverse(chapterUrls);
                                    Collections.reverse(chapterTitles);
                                    Collections.reverse(chapterId);
                                }
                                for (int i : duplicates) {
                                    chapterUrls.set(i,null);
                                    chapterTitles.set(i,null);
                                    sortt.set(i,null);
                                    chapterId.set(i,null);
                                }
                                while (chapterUrls.remove(null));
                                while (chapterTitles.remove(null));
                                while (sortt.remove(null));
                                while (chapterId.remove(null));

                                if(chapterId.size()!=0) {
                                    details.put("key", "chapter");
                                    details.put("chapterTitle", chapterTitles);
                                    details.put("chapterNum", xsize);
                                    details.put("fictionId", fictionId);
                                    details.put("chapterId", chapterId);
                                    details.put("sortt", sortt);
                                    details.put("id", fictionVariable.getId());
                                    boolean process = fictionPipeline.process(details);
                                    if (process) {
                                        jPage.addGoUrls(chapterUrls);
                                        synchronized(Thread.currentThread()) {
                                            allUrl += chapterUrls.size();
                                        }
                                    }
                                }

                            }else{
                                String chapterPageId = ((List<String>) map.get("chapterPage")).get(0);
                                jPage.addTag(UUID.nameUUIDFromBytes(chapterPageId.getBytes()).toString(), fictionId);
                                if(one){
                                    jPage.addTag(UUID.nameUUIDFromBytes((chapterPageId+"chapterUrls").getBytes()).toString(),chapterUrls);
                                    jPage.addTag(UUID.nameUUIDFromBytes((chapterPageId+"chapterTitles").getBytes()).toString(),chapterTitles);
                                    jPage.addTag(UUID.nameUUIDFromBytes((chapterPageId+"details").getBytes()).toString(),details);

                                }else{
                                    chapterUrls.addAll(tag);
                                    chapterTitles.addAll((List<String>)map.get("chapterTitle"));
                                    jPage.addTag(UUID.nameUUIDFromBytes((chapterPageId+"chapterUrls").getBytes()).toString(),chapterUrls);
                                    jPage.addTag(UUID.nameUUIDFromBytes((chapterPageId+"chapterTitles").getBytes()).toString(),chapterTitles);
                                    jPage.addTag(UUID.nameUUIDFromBytes((chapterPageId+"details").getBytes()).toString(),details);

                                }

                            }
                            break;
                        case "contentPage":
                            jPage.addGoUrls(tag);
                            break;
                        case "content":
                            //判断是否还要下一页，还要就把数据放到，以下一页URL为key的map中
                            Object tag1 = jPage.delTag(UUID.nameUUIDFromBytes(jPage.getUrl().getBytes()).toString());
                            if (tag1 != null) {
                                String chapterIdc = null;
                                String contentP = null;
                                String chapterIdi = (String) jPage.delTag(UUID.nameUUIDFromBytes((jPage.getUrl() + "chapterId").getBytes()).toString());
                                if(map.get("contentPage") != null) {
                                    contentP = ((List<String>) map.get("contentPage")).get(0);
                                }else{
                                    contentP = jPage.getUrl();
                                }
                                chapterIdc = UUID.nameUUIDFromBytes(contentP.getBytes()).toString();
                                jPage.addTag(UUID.nameUUIDFromBytes((contentP + "chapterId").getBytes()).toString(), chapterIdi);
                                List<String> ctag = (List<String>) tag1;
                                ctag.addAll(tag);
                                jPage.addTag(chapterIdc, ctag);
                            } else {
                                if (map.get("contentPage") != null) {
                                    String contentP = ((List<String>) map.get("contentPage")).get(0);
                                    String chapterIdc = UUID.nameUUIDFromBytes(contentP.getBytes()).toString();
                                    jPage.addTag(chapterIdc, tag);
                                    jPage.addTag(UUID.nameUUIDFromBytes((contentP + "chapterId").getBytes()).toString(), UUID.nameUUIDFromBytes(jPage.getUrl().getBytes()).toString());
                                }else {
                                    jPage.addTag(UUID.nameUUIDFromBytes(jPage.getUrl().getBytes()).toString(), tag);
                                    jPage.addTag(UUID.nameUUIDFromBytes((jPage.getUrl() + "chapterId").getBytes()).toString(), UUID.nameUUIDFromBytes(jPage.getUrl().getBytes()).toString());
                                }
                            }
                            if (map.get("contentPage") == null) {
                                HashMap<String, Object> cmap = new HashMap<String, Object>();
                                cmap.put("key","content");
                                cmap.put("content", jPage.delTag(UUID.nameUUIDFromBytes(jPage.getUrl().getBytes()).toString()));
                                cmap.put("chapterId", jPage.delTag(UUID.nameUUIDFromBytes((jPage.getUrl() + "chapterId").getBytes()).toString()));
                                cmap.put("id", fictionVariable.getId());
                                cmap.put("infId", infId+"!!!"+allUrl);
                                fictionPipeline.process(cmap);

                            }
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return jPage;
    }

}
